1 2 3 4 5 6 7
   | Daddy told me I should study arm. But I prefer to study my leg!
  Download : http://pwnable.kr/bin/leg.c Download : http://pwnable.kr/bin/leg.asm
  ssh leg@pwnable.kr -p2222 (pw:guest)
   | 
 
leg.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
   | #include <stdio.h> #include <fcntl.h> int key1(){         asm("mov r3, pc\n"); } int key2(){         asm(         "push   {r6}\n"         "add    r6, pc, $1\n"         "bx     r6\n"         ".code   16\n"         "mov    r3, pc\n"         "add    r3, $0x4\n"         "push   {r3}\n"         "pop    {pc}\n"         ".code  32\n"         "pop    {r6}\n"         ); } int key3(){         asm("mov r3, lr\n"); } int main(){         int key=0;         printf("Daddy has very strong arm! : ");         scanf("%d", &key);         if( (key1()+key2()+key3()) == key ){                 printf("Congratz!\n");                 int fd = open("flag", O_RDONLY);                 char buf[100];                 int r = read(fd, buf, 100);                 write(0, buf, r);         }         else{                 printf("I have strong leg :P\n");         }         return 0; }
   | 
 
arm是r0存放函数返回值,pc寄存器指向当前运行指令的后两条指令的地址;
如下是函数key1,
1 2 3 4 5 6 7 8 9 10
   | (gdb) disass key1 Dump of assembler code for function key1:    0x00008cd4 <+0>:     push    {r11}           ; (str r11, [sp, #-4]!)    0x00008cd8 <+4>:     add     r11, sp, #0    0x00008cdc <+8>:     mov     r3, pc    0x00008ce0 <+12>:    mov     r0, r3    0x00008ce4 <+16>:    sub     sp, r11, #0    0x00008ce8 <+20>:    pop     {r11}           ; (ldr r11, [sp], #4)    0x00008cec <+24>:    bx      lr End of assembler dump.
   | 
 
r0 = r3 = pc = 0x00008ce4
如下是函数key2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | Dump of assembler code for function key2:    0x00008cf0 <+0>:     push    {r11}           ; (str r11, [sp, #-4]!)    0x00008cf4 <+4>:     add     r11, sp, #0    0x00008cf8 <+8>:     push    {r6}            ; (str r6, [sp, #-4]!)    0x00008cfc <+12>:    add     r6, pc, #1    0x00008d00 <+16>:    bx      r6    0x00008d04 <+20>:    mov     r3, pc    0x00008d06 <+22>:    adds    r3, #4    0x00008d08 <+24>:    push    {r3}    0x00008d0a <+26>:    pop     {pc}    0x00008d0c <+28>:    pop     {r6}            ; (ldr r6, [sp], #4)    0x00008d10 <+32>:    mov     r0, r3    0x00008d14 <+36>:    sub     sp, r11, #0    0x00008d18 <+40>:    pop     {r11}           ; (ldr r11, [sp], #4)    0x00008d1c <+44>:    bx      lr End of assembler dump.
   | 
 
r0= r3 = 0x00008d08 + 4 = 0x00008d0c 
此处需要说明一下,bx指令的地址,如果最低位是1,说明应当切换到thumb模式。可以看到从0x00008d04后,每条指令的长度都变成了两个字节
如下是key3
1 2 3 4 5 6 7 8 9
   | Dump of assembler code for function key3:    0x00008d20 <+0>:     push    {r11}           ; (str r11, [sp, #-4]!)    0x00008d24 <+4>:     add     r11, sp, #0    0x00008d28 <+8>:     mov     r3, lr    0x00008d2c <+12>:    mov     r0, r3    0x00008d30 <+16>:    sub     sp, r11, #0    0x00008d34 <+20>:    pop     {r11}           ; (ldr r11, [sp], #4)    0x00008d38 <+24>:    bx      lr End of assembler dump.
   | 
 
r0 = r3 = lr = 0x00008d80
lr寄存器保存了函数的返回地址,也就是函数main中调用函数key3处的后一条地址。
因此:key = 0x00008ce4 + 0x00008d0c + 0x00008d80 = 0x0001A770 = 108400
登录上去,看打印出来的log可能是绑定了qemu虚拟机。
1 2 3 4
   | / $ ./leg Daddy has very strong arm! : 108400 Congratz! My daddy has a lot of ARMv5te muscle!
   | 
 
涉及的知识点
- arm函数特点
 
- arm的thumb和arm模式切换